#pragma once
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include "Log.hpp"

using namespace std;
using namespace log;

string space = " ";
string line_break = "\r\n";
string kv_delimiter = ": ";

const std::string default_dir = "wwwroot";
const std::string default_file = "index.html";
const std::string http_version = "HTTP/1.0";
const std::string notfound_page = "wwwroot/404.html";

// 序列化和反序列化的英文是serialization and deserialization，中文是序列化和反序列化。

bool Findline_break(string &str, string &out_data)
{
    auto pos = str.find(line_break);
    if (pos == string::npos)
    {
        LOG(LogLevel::INFO) << "未找到换行符";
        return false;
    }
    out_data = str.substr(0, pos);
    str.erase(0, pos + line_break.size());
    return true;
}

void Findkv_delimiter(string &str, string &key, string &value)
{
    string k, v;
    auto pos = str.find(kv_delimiter);
    k = str.substr(0, pos);
    v = str.substr(pos + kv_delimiter.size());
    key = k;
    value = v;
}

class Handrequest
{
public:
    Handrequest(string allrequest) : _allrequest(allrequest)
    {
        Serialization();
    }
    ~Handrequest() {}
    void Serialization()
    {
        // 请求行的解析
        bool n = Findline_break(_allrequest, _request_line);
        if (n == false)
        {
            LOG(LogLevel::ERROR) << "请求行解析失败";
            return;
        }
        Get_request_line();   // 填入请求方式、请求url、请求版本
        Get_request_header(); // 解析请求头
        Get_request_txet();   // 解析请求正文
    }

    // 解析请求行
    void Get_request_line()
    {
        stringstream str(_request_line);
        str >> _request_way >> _request_url >> _request_version;
    }
    void Get_request_header()
    {
        bool n = true;
        while (n)
        {
            string temp;
            n = Findline_break(_allrequest, temp);
            if (n)
            {
                Findline_break(_allrequest, temp);
                _request_header.push_back(temp);
            }
            else
            {
                break;
            }
        }
        for (int i = 0; i < _request_header.size() - 1; i++)
        {
            string key, value;
            Findkv_delimiter(_request_header[i], key, value);
            _request_kv[key] = value;
        }
    }
    void Get_request_txet()
    {
        _request_txet = _request_header[_request_header.size() - 1];
    }

    // 打印请求信息
    void Print()
    {
        cout << "##############  BEGIN  ####################" << endl;
        cout << "请求行" << _request_way << " " << _request_url << " " << _request_version << endl;
        cout << "请求头" << endl;
        for (auto &e : _request_kv)
        {
            cout << e.first << ":" << e.second << endl;
        }
        cout << "请求正文" << _request_txet << endl;
        cout << "################  END ###################" << endl;
    }


    string Url()
    {
        return _request_url;
    }

private:
    string _allrequest; // 完整请求

    string _request_line;           // 请求行
    vector<string> _request_header; // 请求头
    string _request_txet;           // 请求正文
private:
    string _request_way;     // 请求方式
    string _request_url;     // 请求url
    string _request_version; // 请求版本
    unordered_map<string, string> _request_kv;
};

class Handresponse
{
    Handresponse() : _response_version(http_version) {};
    ~Handresponse() {};

    void Deal_request(Handrequest &request)
    {
        _response_url = request.Url();
    }

    // 构造响应
    void Create_response(Handrequest &request)
    {
        _response_code = 200;
        Deal_request(request);
        if (_response_url.back() == '/')
        {
            _response_url = default_dir + "/" + default_file;
        }
        GetContent();
        if (_content.empty())
        {
            _response_code = 404;
            _response_url = notfound_page;
            GetContent();
        }
        _response_msg = Code2Desc(_response_code);
        SetHeader("Content-Length", std::to_string(_content.size()));
        string mine_type = Suffix();
        SetHeader("Content-Type", Suffix2Desc(mine_type));
        for(auto &e : _header_kv)
        {
            _response_header.push_back(e.first + kv_delimiter + e.second);
        }
    }

    void Serialization()
    {
        string first_line=_response_version + space + std::to_string(_response_code) + space + _response_msg + line_break;
        _ret_message += first_line;
        for(auto &e : _response_header)
        {
            _ret_message += (e + line_break);
        }
        _ret_message += line_break;
        _ret_message += _content;        
    }

    void GetContent()
    {
        _content.clear();
        std::ifstream in(_response_url, std::ios::binary);
        if (!in.is_open())
            return ;
        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);

        _content.resize(filesize);
        in.read((char *)_content.c_str(), filesize);
        in.close();
        LOG(LogLevel::DEBUG) << "content length: " << _content.size();
    }

    std::string Code2Desc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
        case 404:
            return "Not Found";
        default:
            return std::string();
        }
    }
    std::string Suffix2Desc(const std::string &suffix)
    {
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".jpg")
            return "application/x-jpg";
        else
            return "text/html";
    }
    void SetHeader(const string &k, const string &v)
    {
        _header_kv[k] = v;
    }

    std::string Suffix()
    {
        // _uri -> wwwroot/index.html wwwroot/image/1.jpg wwwroot/login.html
        auto pos = _response_url.rfind(".");
        if (pos == std::string::npos)
            return std::string(".html");
        else
            return _response_url.substr(pos);
    }
    string Ret_message()
    {
        return _ret_message;
    }

private:
    string _response_url;     // 请求目录
    string _response_version; // 响应版本
    int _response_code;       // 响应码
    string _response_msg;     // 响应信息

    std::unordered_map<std::string, std::string> _header_kv;
    vector<string> _response_header; // 响应头
    string _content;         //
    string _ret_message;     // 返回信息
    
};